#define TX //SET CODE AS DEFAULT TX
//#define BEACON_LOOP //leave defined for infinite RF beacon mode

#include "common.h"

void goCmdline(void);
void exitFunction(void);
void helpFunction(void);
void dumpArgsStr(void);
void dumpArgsInt(void);
void dumpArgsHex(void);
////////////////////////////

u08 Run;
u08 stream;

extern u08 rf_packet[4];		

void rf_test(void);
void rf_stream(void);
void sampleADs(void);
void streamAD(void);

void initSerialTest(void);
void init_ADC(void);
void i2c_test(void);

void terminal_test(void);
//void buzzerPOST(void);
//void LEDPOST(void);
//void LEDPOST2(void);

void timer0Attach(void);
//void timer0Overflow(void);
void timer0SetPrescale(void);

static inline void led_blink(void)
{
	 sbi(LED_PORT, LED_PIN);
   // _delay_ms(100);
     cbi(LED_PORT, LED_PIN); 
}


/*
ISR(USART0_RX_vect )      
{
	// service UART0 receive interrupt
	//cmdflg = 1;	
	uartReceiveService(0);
}
*/

///////////////printf -> uart
    static int uart_putchar(char c, FILE *stream);

    static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
                                             _FDEV_SETUP_WRITE);

    static int uart_putchar(char c, FILE *stream)
    {

      if (c == '\n')
        uart_putchar('\r', stream);
      loop_until_bit_is_set(UCSRA, UDRE);
      UDR = c;
      return 0;
    }

/////////
void init_common(void)
{
	serialInit(); 
	stdout = &mystdout;
	printf(LAMBDA_STR);

	init_mcu();
	flags = 0;//common.h
	error = ERR_NONE;
	
	buzzerPOST();
	LEDPOST();
	//LEDPOST2();

	timerInit(); //timer.c
	//timerAttach(0, timer0Overflow());
	//timer0SetPrescaler(TIMER_CLK_DIV1024);

	init_ADC();

//	i2c_test();

	//serialTest();

	#ifdef BEACON_LOOP
		printf("ENTERING RF BEACON LOOP\n");
		rf_test();
	#endif

	//rf_test();

	//#ifdef FPGA
	rprintfInit(uart0SendByte);
	//#endif
	
	//terminal_test();
	vt100Init();
	goCmdline();
	Run = TRUE;//global variable for escaping loopsflag_packetproc = 0;
}
/////////
int main(void)
{  

  init_common();
 
  
  while(1)
  {
	//CallStateMachine[bCurState]();   //Call the current state function  
    cmdlineMainLoop();//process command lines
	#warning "REMINDER: SELECT INTERRUPT SOURCES FOR OPTIMIZATION"
	
	#ifdef PROBE
		lambdaprobe();
	#else
		lambdaboard();
	#endif

  }	
  return 0;	  												  
}


/*
void timer0Overflow(void)
{
#ifdef FPGA	
	u08 i;
	u08 packet[] ={0x01, 0x10, 0xff, 0xff, 0xff};
	
	packet[1] = a2dConvert8bit(0);
	for(i = 0; i < 5; i++)
	  tx(packet[i]);
	  
	led_blink();  
#endif
}
*/
void timer0Attach(void)
{
	  timerAttach(0, timer0Overflow);
	  rprintf("Attached timer0Overflow()\n\r");
}
void timer0SetPrescale(void)
{
	//  timer0SetPrescaler(cmdlineGetArgInt(1));
	  printf("Set overflow to: %02X\n", (u08)cmdlineGetArgHex(1));
}

void rf_test(void)
{
    #ifndef PROBE
		//power on RF module from pin, hah
		RFDDR |= _BV(RFGNDPIN);
		cbi(RFPORT, RFGNDPIN);
	#endif

	    rf_packet[0] = 'l';
        rf_packet[1] = 'a';
        rf_packet[2] = 'm';
        
		#ifdef BEACON_LOOP
			configure_transmitter();
			
			while(1) {
				counter++; 
				rf_packet[3] = counter;
				transmit_data();
				_delay_ms(1);
			}
		#endif
		
//		counter++;
    
//      printstr("Sending data...\n");

		configure_receiver();

        printstr("Awaiting RX_DR assertion...\n");
	
		while( (RFPIN & _BV(RX_DR)) == 0);
		
		if((RFPIN & _BV(RX_DR))) {//We have data!
			receive_data();
			printf("\nData Received: %02X %02X %02X %02X\n", rf_packet[0], rf_packet[1], rf_packet[2], rf_packet[3]);
			led_blink();
		}else{
			printstr("No data found!\n");
		}

       // _delay_ms(1000); //Have a second between transmissions just for evaluation
}
void rf_stream(void)
{	
	do{
		while( (RFPIN & _BV(RX_DR)) == 0);
		
		if((RFPIN & _BV(RX_DR))) {//We have data!
			receive_data();
			printf("\nData Received: %02X %02X %02X %02X\n", rf_packet[0], rf_packet[1], rf_packet[2], rf_packet[3]);
			led_blink();
		}else{
			printstr("No data found!\n");
		}
	} while(Run);
}

void buzzerPOST(void)
{
  //BUZZER POST
  printf("BUZZER POST\n");
  sbi(DDRA, BUZZER_PIN);  //set output
  sbi(BUZZER_PORT, BUZZER_PIN); 
  _delay_ms(100);
  cbi(BUZZER_PORT, BUZZER_PIN); 
}

void LEDPOST(void)
{
    printf("LED POST\n");
	sbi(LED_DDR, LED_PIN);
	              
    cbi(LED_PORT, LED_PIN);              
	_delay_ms(250); 
	sbi(LED_PORT, LED_PIN);
	_delay_ms(250);
	cbi(LED_PORT, LED_PIN);
	_delay_ms(250); 
	sbi(LED_PORT, LED_PIN);
	_delay_ms(250);
	cbi(LED_PORT, LED_PIN);
}

void sampleADs(void)
{
		u08 i;
		
		// sample all a2d channels and print them to the terminal
		vt100ClearScreen();
		rprintf("A/D sampler...\n");
		vt100SetCursorPos(2,1);
		for(i=0; i<8; i++)
		{
			rprintf("Channel %d: %d   \r\n", i, a2dConvert8bit(i));
		}
		// print the sample number so far
		//rprintf("Sample # : %d   \r\n", a++);
}

void goCmdline(void)
{

	// print welcome message
	vt100ClearScreen();

	vt100SetCursorPos(1,0);

	rprintfProgStrM(LAMBDA_STR);

	// initialize cmdline system
	cmdlineInit();

	// direct cmdline output to uart (serial port)
	cmdlineSetOutputFunc(uart0SendByte);

	// add commands to the command database
	cmdlineAddCommand((u08*)"exit",		exitFunction);
	cmdlineAddCommand((u08*)"help",		helpFunction);
	//cmdlineAddCommand("dumpargs1",	dumpArgsStr);
	//cmdlineAddCommand("dumpargs2",	dumpArgsInt);
	//cmdlineAddCommand("dumpargs3",	dumpArgsHex);
	
	cmdlineAddCommand((u08*)"buzz",	buzzerPOST);
	cmdlineAddCommand((u08*)"blink", LEDPOST);
//	cmdlineAddCommand((u08*)"rftest", rf_test);
	cmdlineAddCommand((u08*)"rfstream", rf_stream);
//	cmdlineAddCommand((u08*)"timer0attach", timer0Attach);
//	cmdlineAddCommand((u08*)"timer0setprescale", timer0SetPrescale);
//	cmdlineAddCommand((u08*)"streamads", streamADC);
	cmdlineAddCommand((u08*)"readads", sampleADs);
	// send a CR to cmdline input to stimulate a prompt
	cmdlineInputFunc('\r');

	// set state to run
	//Run = TRUE;
 // cmdlineMainLoop();
	// main loop
	/*
	while(Run)
	{
		// pass characters received on the uart (serial port)
		// into the cmdline processor
		//while(uartReceiveByte(0,&c)) cmdlineInputFunc(c);
		// run the cmdline execution functions
		cmdlineMainLoop();
	}
*/
	//rprintfCRLF();
	//rprintf("Exited program!\r\n");
}

void exitFunction(void)
{
	// to exit, we set Run to FALSE
	Run = FALSE;
}

void helpFunction(void)
{
	rprintfCRLF();

	rprintf("Available commands are:\r\n");
	rprintf("help      - displays available commands\r\n");
	rprintf("dumpargs1 - dumps command arguments as strings\r\n");
	rprintf("dumpargs2 - dumps command arguments as decimal integers\r\n");
	rprintf("dumpargs3 - dumps command arguments as hex integers\r\n");
	rprintf("buzz - buzzerPOST\r\n");
	rprintf("blink - \r\n");
	rprintf("rftest - \r\n");
	rprintf("timer0attach\r\n");
	rprintf("timer0setprescale\r\n");
	rprintf("readads\r\n");
	
	//rprintf("ports
	rprintfCRLF();
}

void dumpArgsStr(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as strings\r\n");

	rprintfProgStrM("Arg0: "); rprintfStr((char*)cmdlineGetArgStr(0)); rprintfCRLF();
	rprintfProgStrM("Arg1: "); rprintfStr((char*)cmdlineGetArgStr(1)); rprintfCRLF();
	rprintfProgStrM("Arg2: "); rprintfStr((char*)cmdlineGetArgStr(2)); rprintfCRLF();
	rprintfProgStrM("Arg3: "); rprintfStr((char*)cmdlineGetArgStr(3)); rprintfCRLF();
	rprintfCRLF();
}

void dumpArgsInt(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as integers\r\n");

	// printf %d will work but only if your numbers are less than 16-bit values
	//rprintf("Arg1 as int: %d\r\n", cmdlineGetArgInt(1));
	//rprintf("Arg2 as int: %d\r\n", cmdlineGetArgInt(2));
	//rprintf("Arg3 as int: %d\r\n", cmdlineGetArgInt(3));

	// printfNum is good for longs too
	rprintf("Arg1 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(1)); rprintfCRLF();
	rprintf("Arg2 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(2)); rprintfCRLF();
	rprintf("Arg3 as int: "); rprintfNum(10, 10, TRUE, ' ', cmdlineGetArgInt(3)); rprintfCRLF();
	rprintfCRLF();
}

void dumpArgsHex(void)
{
	rprintfCRLF();
	rprintf("Dump arguments as hex integers\r\n");

	rprintf("Arg1 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(1)); rprintfCRLF();
	rprintf("Arg2 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(2)); rprintfCRLF();
	rprintf("Arg3 as hex: "); rprintfNum(16, 8, FALSE, ' ', cmdlineGetArgHex(3)); rprintfCRLF();
	rprintfCRLF();
}

//-----------------------------
/*
void Initialization(void)
{
    char tst;           // dummy

    OSCCAL_calibration();       // calibrate the OSCCAL byte
        
    CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable

    // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
    CLKPR = (1<<CLKPS1) | (1<<CLKPS0);

    // Disable Analog Comparator (power save)
    ACSR = (1<<ACD);

    // Disable Digital input on PF0-2 (power save)
    DIDR0 = (7<<ADC0D);

    // mt PORTB = (15<<PORTB0);       // Enable pullup on 
    PORTB = (15<<PB0);       // Enable pullup on 
    // mt PORTE = (15<<PORTE4);
    PORTE = (15<<PE4);

    sbiBF(DDRB, 5);               // set OC1A as output
    sbiBF(PORTB, 5);              // set OC1A high
            
    Button_Init();              // Initialize pin change interrupt on joystick
    
    RTC_init();                 // Start timer2 asynchronous, used for RTC clock

    Timer0_Init();              // Used when playing music etc.

    USART_Init(12);             // Baud rate = 9600bps
    
    DF_SPI_init();              // init the SPI interface to communicate with the DataFlash
    
    tst = Read_DF_status();

    DF_CS_inactive;             // disable DataFlash
        
    LCD_Init();                 // initialize the LCD
}
*/

/*
void i2c_test(void)
{
 
  unsigned char messageBuf[MESSAGEBUF_SIZE];
  unsigned char TWI_targetSlaveAddress, temp, pressedButton, myCounter=0;

  USI_TWI_Master_Initialise();
  
 // __enable_interrupt();
  
  TWI_targetSlaveAddress   = 0xAA;

	  //write analog value to DAC
	  //Ctrl/MS-Byte:
	  //0 0 PD1 PD0 D7 D6 D5 D4 
	  //D3 D2 D1 D0 X X X X
	  //PD0, PD1: 0 0 normal operation
	  //1 0 0 1 1 0 A0 R/W
		u08 voltage, i;
	  while(1)
	  {
		for (i = 0; i < 255; i++)
		{
			messageBuf[0] = (DACFILTER_ADDR | 2) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
			messageBuf[1] = 0x00 | (i >> 4);             // The first byte is used for commands.
			messageBuf[2] = 0x00 | (i<<4);                        // The second byte is used for the data.
			temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 3 );  
			// _delay_us(100);
			// _delay_us(50);
			//_delay_us(25);
			// _delay_us(1); //ok
			__builtin_avr_delay_cycles(1); //ok gives 41Hz triangle; 41Hz*256 = 10496 samples/sec
		}
	  }

      switch ( pressedButton ) 
      {
        // Send a Generall Call
        case (0):     // 
          messageBuf[0] = TWI_GEN_CALL;     // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = 0xAA;             // The command or data to be included in the general call.
          temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 2 );
          break;

        // Send a Address Call, sending a command and data to the Slave          
        case (1):      
          messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = TWI_CMD_MASTER_WRITE;             // The first byte is used for commands.
          messageBuf[2] = myCounter;                        // The second byte is used for the data.
          temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 3 );
          break;

        // Send a Address Call, sending a request, followed by a resceive          
        case (2):      
          // Send the request-for-data command to the Slave
          messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = TWI_CMD_MASTER_READ;             // The first byte is used for commands.
          temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 2 );

          // One might need to delay before proceding to enable the slave to interpret the last message,
          // and prepare the next request. Or as in this simple sample rerun the request until he responds. 

          // Transmit request and get the received data from the transceiver buffer
          messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
          do
            temp = USI_TWI_Start_Transceiver_With_Data( messageBuf, 2 );
          while (USI_TWI_Get_State_Info() == USI_TWI_NO_ACK_ON_ADDRESS);
                 
     //     PORTB = messageBuf[1];        // Store data on PORTB.
          break;

        case (3):      
          // Send the request-for-data command to the Slave
          if (TWI_targetSlaveAddress == 0x10)
           TWI_targetSlaveAddress = 0x15;
          else
           TWI_targetSlaveAddress = 0x10;
          break;
                              
        // Get status from Transceiver and put it on PORTB
        case (5):
          //PORTB = USI_TWI_Get_State_Info();
          break;

        // Increment myCounter and put it on PORTB          
        case (6):      
          //PORTB = ++myCounter;        
          break;
          
        // Reset myCounter and put it on PORTB
        case (7):      
          //PORTB = myCounter = 0;        
          break;  
      }
      
      if (!temp)    // One of the operations failed.
      {             // Use TWI status information to detemine cause of failure and take appropriate actions. 
       // TWI_Act_On_Failure_In_Last_Transmission( USI_TWI_Get_State_Info( ) );  
       // __no_operation(); // Put own code here.
      }

}
*/
////////////////////////////////////////

